<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>虚拟滚动表格 - 无限滚动定时更新</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 1000px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        .table-header {
            background-color: #f8f9fa;
            border-bottom: 2px solid #dee2e6;
            padding: 15px;
        }
        .table-header h3 {
            margin: 0 0 10px 0;
            color: #495057;
        }
        .controls {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
        }
        .controls button {
            padding: 8px 16px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }
        .controls button:hover { background-color: #0056b3; }
        .controls button:disabled { background-color: #6c757d; cursor: not-allowed; }
        
        .config {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            margin-bottom: 10px;
            align-items: end;
        }
        .config-item {
            display: flex;
            flex-direction: column;
            min-width: 150px;
        }
        .config-item label {
            font-size: 12px;
            color: #6c757d;
            margin-bottom: 4px;
        }
        .config-item input {
            padding: 6px;
            border: 1px solid #ddd;
            border-radius: 4px;
        }

        .table-container {
            height: 500px;
            overflow: auto;
            position: relative;
            border-top: 1px solid #dee2e6;
        }
        .table-wrapper {
            position: relative;
            width: 100%;
        }
        .table {
            width: 100%;
            table-layout: fixed;
            border-collapse: collapse;
        }
        .table thead {
            position: sticky;
            top: 0;
            z-index: 5;
        }
        .table th {
            background-color: #e9ecef;
            padding: 12px;
            text-align: left;
            font-weight: 600;
            color: #495057;
            border-bottom: 2px solid #dee2e6;
        }
        .table td {
            padding: 12px;
            border-bottom: 1px solid #dee2e6;
            word-break: break-word;
            vertical-align: top;
            height: 48px;
        }
        .table tbody tr:nth-child(even) {
            background-color: #f8f9fa;
        }
        .table tbody tr:hover {
            background-color: #e9ecef;
        }
        .loading {
            text-align: center;
            padding: 20px;
            color: #6c757d;
        }
        .data-info {
            padding: 10px 15px;
            background-color: #f8f9fa;
            border-top: 1px solid #dee2e6;
            font-size: 14px;
            color: #6c757d;
            display: flex;
            justify-content: space-between;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="table-header">
            <h3>虚拟滚动表格 - 无限滚动定时更新</h3>
            
            <div class="config">
                <div class="config-item">
                    <label>滚动速度 (px/帧):</label>
                    <input id="scrollSpeed" type="number" value="3" min="1" max="20">
                </div>
                <div class="config-item">
                    <label>数据更新间隔 (ms):</label>
                    <input id="updateInterval" type="number" value="3000" min="1000">
                </div>
                <div class="config-item">
                    <label>批量加载数量:</label>
                    <input id="batchSize" type="number" value="200" min="50">
                </div>
                <div class="config-item">
                    <button id="applyConfig">应用配置</button>
                </div>
            </div>
            
            <div class="controls">
                <button id="startScroll">开始自动滚动</button>
                <button id="stopScroll" disabled>停止自动滚动</button>
                <button id="refreshData">刷新数据</button>
                <button id="updateDataBtn">手动更新数据</button>
            </div>
        </div>

        <div class="table-container" id="tableContainer">
            <div class="table-wrapper">
                <table class="table">
                    <thead>
                        <tr>
                            <th style="width: 80px;">ID</th>
                            <th style="width: 150px;">名称</th>
                            <th style="width: 120px;">类型</th>
                            <th style="width: 150px;">更新时间</th>
                            <th>描述</th>
                        </tr>
                    </thead>
                    <tbody id="tableBody">
                        <!-- 虚拟滚动行将在这里动态生成 -->
                    </tbody>
                </table>
            </div>
        </div>

        <div class="data-info">
            <span>总数据条数: <span id="totalCount">0</span></span>
            <span>可见行数: <span id="visibleCount">0</span></span>
            <span>状态: <span id="status">就绪</span></span>
        </div>
    </div>

    <script>
        // 工具函数：生成随机字符串
        function randomString(length) {
            const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            let result = '';
            for (let i = 0; i < length; i++) {
                result += chars.charAt(Math.floor(Math.random() * chars.length));
            }
            return result;
        }
        function generateRandomText(minLength = 20, maxLength = 100) {
        const paragraphs = [];
        const paragraphCount = Math.floor(Math.random() * 3) + 1; // 1-3 段
        for (let i = 0; i < paragraphCount; i++) {
            const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;
            paragraphs.push(randomString(length));
        }
        return paragraphs.join('<br><br>');
    }

        // 生成数据项
        function generateDataItem(id) {
            const types = ['类型A', '类型B', '类型C', '类型D', '类型E'];
            const now = new Date();
            const randomTime = new Date(now.getTime() - Math.floor(Math.random() * 7 * 24 * 60 * 60 * 1000));
            return {
                id: id,
                name: `项目 ${id} - ${randomString(8)}`,
                type: types[Math.floor(Math.random() * types.length)],
                updateTime: randomTime.toLocaleString('zh-CN'),
                description: generateRandomText()
            };
        }

        // 虚拟滚动表格类
        class VirtualScrollTable {
            constructor(options = {}) {
                // DOM引用
                this.container = document.getElementById('tableContainer');
                this.tableBody = document.getElementById('tableBody');
                this.totalCountEl = document.getElementById('totalCount');
                this.visibleCountEl = document.getElementById('visibleCount');
                this.statusEl = document.getElementById('status');
                this.startScrollBtn = document.getElementById('startScroll');
                this.stopScrollBtn = document.getElementById('stopScroll');
                this.refreshDataBtn = document.getElementById('refreshData');
                this.updateDataBtn = document.getElementById('updateDataBtn');

                // 配置参数
                this.scrollSpeed = options.scrollSpeed || 3;
                this.dataUpdateInterval = options.updateInterval || 3000;
                this.batchSize = options.batchSize || 200;
                this.defaultRowHeight = 48; // 默认行高
                this.bufferSize = 10; // 缓冲区大小
                this.maxCount = 50; // 最大显示行数
                this.maxDataLength = options.maxDataLength || 20000; // 最大缓存数据量，防止内存溢出
                this.trimThreshold = 0.7; // 数据淘汰阈值（当数据量达到maxDataLength的70%时触发淘汰）
                this.trimInterval = 5000; // 数据淘汰检查间隔（毫秒）
                
                // 状态
                this.data = []; // 原始数据（重命名更清晰）
                this.pendingUpdates = []; // 待更新数据（重命名更清晰）
                this.rowHeights = []; // 每行高度数组（重命名更清晰）
                this.isAutoScrolling = false;
                this.scrollIndex = 0; // 当前滚动位置对应的索引
                this.prevScrollIndex = -1; // 上一次渲染的索引
                this.endIndex = 0; // 结束索引
                this.idCounter = 1; // ID计数器，确保ID持续增长
                this._scrollRAF = null;
                this._autoScrollRAF = null;
                this._updateTimer = null;
                this._trimTimer = null; // 数据淘汰定时器
                this.taskQueue = []; // 任务队列（重命名更清晰）
                this.isLoading = false; // 加载状态
                this.totalDataCount = 0; // 记录总共生成的数据量（包括已被淘汰的数据）
                this.rowRenderer = options.rowRenderer || this._defaultRowRenderer; // 自定义行渲染器
                
                // 错误处理
                this.errorHandlers = {
                    dataLoad: (error) => console.error('数据加载失败:', error),
                    dataUpdate: (error) => console.error('数据更新失败:', error),
                    render: (error) => console.error('渲染错误:', error)
                };

                // 初始化
                this._init();
            }

            _init() {
                // 绑定事件
                this.container.addEventListener('scroll', this._onScroll.bind(this));
                this.startScrollBtn.addEventListener('click', this.startAutoScroll.bind(this));
                this.stopScrollBtn.addEventListener('click', this.stopAutoScroll.bind(this));
                this.refreshDataBtn.addEventListener('click', this.refreshData.bind(this));
                this.updateDataBtn.addEventListener('click', this.updateData.bind(this));

                // 初始化任务队列，包含数据更新任务
                const updateTask = () => {
                    try {
                        // 确保数据按ID顺序更新，避免ID混乱
                        if (this.pendingUpdates.length > 0) {
                            // 先按ID排序pendingUpdates
                            this.pendingUpdates.sort((a, b) => a.id - b.id);
                            
                            // 根据ID查找对应位置进行更新，确保ID顺序不变
                            this.pendingUpdates.forEach(newItem => {
                                const index = this.data.findIndex(item => item.id === newItem.id);
                                if (index !== -1) {
                                    this.data[index] = newItem;
                                }
                            });
                            
                            // 清空待更新数据
                            this.pendingUpdates = [];
                        }
                    } catch (error) {
                        this.errorHandlers.dataUpdate(error);
                    }
                };
                this.taskQueue.push(updateTask);

                // 加载初始数据
                this.loadInitialData();

                // 启动定时更新
                this.startDataUpdateTimer();
                
                // 启动数据淘汰定时器
                this.startTrimTimer();
            }
            
            // 默认行渲染器
            _defaultRowRenderer(item) {
                return `
                    <td>${item.id}</td>
                    <td>${item.name}</td>
                    <td>${item.type}</td>
                    <td>${item.updateTime}</td>
                    <td>${item.description}</td>
                `;
            }

            // 加载初始数据
            loadInitialData() {
                this.statusEl.textContent = '加载中...';
                
                try {
                    // 生成初始数据，使用idCounter确保ID连续
                    this.data = Array.from({length: this.batchSize}, (_, i) => {
                        const id = this.idCounter++;
                        return generateDataItem(id);
                    });
                    
                    // 初始化行高数据
                    this.rowHeights = Array(this.batchSize).fill(this.defaultRowHeight);
                    this.totalDataCount = this.batchSize; // 更新总数据量
                    this.totalCountEl.textContent = this.totalDataCount;
                    this.statusEl.textContent = '就绪';
                    
                    // 重置索引
                    this.scrollIndex = 0;
                    this.prevScrollIndex = -1;
                    this.endIndex = Math.min(this.maxCount + this.bufferSize, this.data.length);
                    
                    // 初始渲染
                    this.updateVisibleRows();
                } catch (error) {
                    this.errorHandlers.dataLoad(error);
                    this.statusEl.textContent = '加载失败';
                }
            }
            
            // 数据淘汰机制 - 只保留当前可视区域和缓冲区的数据
            trimData() {
                // 检查是否达到淘汰阈值
                if (this.data.length <= this.maxDataLength * this.trimThreshold) return;
                
                try {
                    // 计算要保留的起始和结束索引，保留更大的缓冲区以确保滚动流畅
                    const safeBufferSize = Math.max(this.bufferSize * 2, 50); // 确保最小缓冲区大小
                    const safeStartIndex = Math.max(0, this.scrollIndex - safeBufferSize);
                    const safeEndIndex = Math.min(
                        this.data.length, 
                        this.scrollIndex + this.maxCount + safeBufferSize
                    );
                    
                    // 确保至少保留一定数量的数据
                    const minKeepCount = Math.min(this.maxDataLength, 1000); // 最小保留1000条或maxDataLength取较小值
                    const keepCount = safeEndIndex - safeStartIndex;
                    
                    // 如果保留的数据少于最小数量，调整保留范围
                    if (keepCount < minKeepCount) {
                        const expandAmount = Math.floor((minKeepCount - keepCount) / 2);
                        const newSafeStartIndex = Math.max(0, safeStartIndex - expandAmount);
                        const newSafeEndIndex = Math.min(this.data.length, safeEndIndex + expandAmount);
                        
                        // 再次检查，如果还是不够，则取尽可能多的数据
                        if (newSafeEndIndex - newSafeStartIndex < minKeepCount) {
                            const halfMinKeep = Math.floor(minKeepCount / 2);
                            const centeredStart = Math.max(0, this.scrollIndex - halfMinKeep);
                            const centeredEnd = Math.min(this.data.length, this.scrollIndex + halfMinKeep);
                            
                            // 如果居中截取仍然不够，则从当前位置向前尽可能多取
                            if (centeredEnd - centeredStart < minKeepCount && centeredStart === 0) {
                                const finalEnd = Math.min(this.data.length, minKeepCount);
                                this._doTrimData(0, finalEnd);
                            } else {
                                this._doTrimData(centeredStart, centeredEnd);
                            }
                        } else {
                            this._doTrimData(newSafeStartIndex, newSafeEndIndex);
                        }
                    } else {
                        this._doTrimData(safeStartIndex, safeEndIndex);
                    }
                } catch (error) {
                    console.error('数据淘汰失败:', error);
                }
            }
            
            // 执行实际的数据淘汰操作
            _doTrimData(startIndex, endIndex) {
                // 只保留必要的数据
                this.data = this.data.slice(startIndex, endIndex);
                this.rowHeights = this.rowHeights.slice(startIndex, endIndex);
                
                // 调整相关索引
                this.scrollIndex = Math.max(0, this.scrollIndex - startIndex);
                this.endIndex = Math.min(this.endIndex - startIndex, this.data.length);
                
                // 记录内存使用情况（调试用）
                console.log(`数据已淘汰，当前数据量: ${this.data.length}`);
            }
            
            // 启动数据淘汰定时器
            startTrimTimer() {
                this.stopTrimTimer(); // 先停止旧的定时器
                
                this._trimTimer = setInterval(() => {
                    this.trimData();
                }, this.trimInterval);
            }
            
            // 停止数据淘汰定时器
            stopTrimTimer() {
                if (this._trimTimer) {
                    clearInterval(this._trimTimer);
                    this._trimTimer = null;
                }
            }

            // 滚动事件处理
            _onScroll() {
                if (this._scrollRAF) return;
                
                this._scrollRAF = requestAnimationFrame(() => {
                    this._scrollRAF = null;
                    this._handleScroll();
                });
            }

            // 滚动变化处理
            _handleScroll() {
                try {
                    // 计算当前滚动位置对应的数据索引
                    this._updateScrollIndex();
                    this.checkNeedMoreData();
                    
                    // 如果索引变化超过阈值，则更新视图
                    const indexDiff = Math.abs(this.scrollIndex - this.prevScrollIndex);
                    
                    // 根据滚动速度动态调整更新频率
                    const shouldUpdate = indexDiff > (this.isAutoScrolling ? 1 : 3);
                    
                    if (shouldUpdate) {
                        this.prevScrollIndex = this.scrollIndex;
                        this.updateVisibleRows();
                    }
                } catch (error) {
                    console.error('滚动处理失败:', error);
                }
            }

            // 更新滚动索引位置
            _updateScrollIndex() {
                const { scrollTop } = this.container;
                let accumulatedHeight = 0;

                // 优化：使用二分查找加速定位
                if (this.rowHeights.length > 1000) {
                    this.scrollIndex = this._binarySearchScrollIndex(scrollTop);
                } else {
                    // 对于少量数据，线性查找仍可接受
                    for (let i = 0; i < this.rowHeights.length; i++) {
                        accumulatedHeight += this.rowHeights[i];
                        if (accumulatedHeight > scrollTop) {
                            this.scrollIndex = i;
                            break;
                        }
                    }
                }

                // 更新结束索引
                this.endIndex = Math.min(this.scrollIndex + this.maxCount + this.bufferSize, this.data.length);
            }
            
            // 使用二分查找优化滚动索引计算
            _binarySearchScrollIndex(scrollTop) {
                let low = 0;
                let high = this.rowHeights.length - 1;
                let accumulatedHeight = 0;
                
                // 预先计算前缀和数组用于二分查找
                const prefixSums = [];
                let sum = 0;
                for (let i = 0; i < this.rowHeights.length; i++) {
                    sum += this.rowHeights[i];
                    prefixSums.push(sum);
                    
                    if (sum > scrollTop) {
                        return i;
                    }
                }
                
                return this.rowHeights.length - 1;
            }

            // 检查是否需要加载更多数据
            checkNeedMoreData() {
                // 提前预加载，当剩余数据少于可视区域2倍时开始加载
                const remainingItems = this.data.length - this.scrollIndex;
                const threshold = this.maxCount * 2 + this.bufferSize;
                
                if (remainingItems < threshold && !this.isLoading) {
                    this.loadMoreData();
                }
            }

            // 兼容旧方法名
            checkLoadMore() {
                this.checkNeedMoreData();
            }

            // 加载更多数据
            loadMoreData() {
                this.isLoading = true;
                this.statusEl.textContent = '加载更多...';
                
                try {
                    // 模拟异步加载
                    setTimeout(() => {
                        try {
                            // 生成新数据，使用idCounter确保ID连续递增
                            const newData = Array.from({length: this.batchSize}, (_, i) => {
                                const id = this.idCounter++;
                                return generateDataItem(id);
                            });
                            
                            // 添加新数据
                            this.data = [...this.data, ...newData];
                            
                            // 为新数据初始化高度（更高效的方式）
                            const newHeights = Array(this.batchSize).fill(this.defaultRowHeight);
                            this.rowHeights = [...this.rowHeights, ...newHeights];
                            
                            // 更新数据计数
                            this.totalDataCount += this.batchSize;
                            this.totalCountEl.textContent = this.totalDataCount;
                            
                            // 更新结束索引
                            this.endIndex = Math.min(this.scrollIndex + this.maxCount + this.bufferSize, this.data.length);
                            
                            // 如果当前正在查看底部区域，更新视图
                            const isNearBottom = this.scrollIndex > this.data.length - threshold - 100;
                            if (isNearBottom) {
                                this.updateVisibleRows();
                            }
                            
                            // 执行数据淘汰检查
                            if (this.data.length > this.maxDataLength * this.trimThreshold) {
                                this.trimData();
                            }
                            
                        } catch (error) {
                            this.errorHandlers.dataLoad(error);
                        } finally {
                            this.isLoading = false;
                            this.statusEl.textContent = '就绪';
                        }
                    }, 300);
                } catch (error) {
                    this.errorHandlers.dataLoad(error);
                    this.isLoading = false;
                    this.statusEl.textContent = '加载失败';
                }
            }

            // 更新可见行
            updateVisibleRows() {
                try {
                    // 确保滚动索引正确
                    this._updateScrollIndex();
                    
                    const adjustedStartIndex = Math.max(0, this.scrollIndex - this.bufferSize);
                    
                    // 计算顶部占位符高度（优化：避免重复计算）
                    let topHeight = 0;
                    for (let i = 0; i < adjustedStartIndex && i < this.rowHeights.length; i++) {
                        topHeight += this.rowHeights[i];
                    }
                    
                    // 清空表格体
                    this.tableBody.innerHTML = '';
                    
                    // 添加顶部占位符
                    const topSpacer = document.createElement('div');
                    topSpacer.style.height = `${topHeight}px`;
                    topSpacer.style.position = 'relative';
                    this.tableBody.appendChild(topSpacer);
                    
                    // 添加可见行
                    const fragment = document.createDocumentFragment();
                    for (let i = adjustedStartIndex; i < this.endIndex; i++) {
                        const item = this.data[i];
                        if (!item) continue;
                        
                        const row = document.createElement('tr');
                        try {
                            // 使用自定义或默认渲染器
                            row.innerHTML = this.rowRenderer(item);
                        } catch (renderError) {
                            this.errorHandlers.render(renderError);
                            // 回退到简单渲染
                            row.innerHTML = `
                                <td>${item.id}</td>
                                <td>渲染错误</td>
                                <td>-</td>
                                <td>-</td>
                                <td>该行渲染出现错误</td>
                            `;
                        }
                        fragment.appendChild(row);
                    }
                    
                    this.tableBody.appendChild(fragment);
                    
                    // 计算底部占位符高度
                    let totalHeight = 0;
                    let renderedHeight = 0;
                    
                    // 计算总高度
                    for (let height of this.rowHeights) {
                        totalHeight += height;
                    }
                    
                    // 计算已渲染行的高度
                    for (let i = adjustedStartIndex; i < this.endIndex && i < this.rowHeights.length; i++) {
                        renderedHeight += this.rowHeights[i];
                    }
                    
                    const bottomHeight = Math.max(0, totalHeight - topHeight - renderedHeight);
                    
                    const bottomSpacer = document.createElement('div');
                    bottomSpacer.style.height = `${bottomHeight}px`;
                    bottomSpacer.style.position = 'relative';
                    this.tableBody.appendChild(bottomSpacer);
                    
                    // 更新可见计数
                    const visibleCount = Math.min(this.endIndex - adjustedStartIndex, this.data.length);
                    this.visibleCountEl.textContent = visibleCount;
                    
                    // 更新行高数据（使用requestAnimationFrame确保DOM已渲染）
                    requestAnimationFrame(() => {
                        this._updateRowHeights(adjustedStartIndex);
                    });
                } catch (error) {
                    this.errorHandlers.render(error);
                }
            }

            // 更新行高数据
            _updateRowHeights(startIndex) {
                try {
                    const rows = this.tableBody.querySelectorAll('tr');
                    // 更新每一行的高度数据
                    for (let i = 0; i < rows.length; i++) {
                        const actualIndex = startIndex + i;
                        if (actualIndex < this.rowHeights.length) {
                            const newHeight = rows[i].offsetHeight;
                            // 只有当高度发生显著变化时才更新，减少不必要的计算
                            if (Math.abs(this.rowHeights[actualIndex] - newHeight) > 2) {
                                this.rowHeights[actualIndex] = newHeight;
                            }
                        }
                    }
                } catch (error) {
                    console.error('更新行高失败:', error);
                }
            }

            // 开始自动滚动
            startAutoScroll() {
                if (this.isAutoScrolling) return;
                
                this.isAutoScrolling = true;
                this.startScrollBtn.disabled = true;
                this.stopScrollBtn.disabled = false;
                
                let lastTime = performance.now();
                let frameCount = 0; // 用于控制优化操作频率
                
                const step = (currentTime) => {
                    if (!this.isAutoScrolling) return;
                    
                    const deltaTime = currentTime - lastTime;
                    lastTime = currentTime;
                    
                    // 计算滚动距离（考虑帧率变化，确保速度稳定）
                    const scrollDistance = Math.min((this.scrollSpeed * deltaTime) / 16, 20); // 限制最大滚动距离
                    
                    // 执行滚动
                    this.container.scrollTop += scrollDistance;
                    
                    // 滚动变化处理
                    this._handleScroll();
                    
                    // 检查是否需要加载更多数据（提前触发加载）
                    const totalHeight = this.rowHeights.reduce((sum, height) => sum + height, 0);
                    if (this.container.scrollTop >= totalHeight - this.container.clientHeight * 3) {
                        this.checkNeedMoreData();
                    }
                    
                    // 每30帧执行一次优化检查，而不是随机触发
                    frameCount++;
                    if (frameCount >= 30) {
                        frameCount = 0;
                        // 检查是否需要立即执行数据淘汰
                        if (this.data.length > this.maxDataLength * 0.9) { // 当达到90%时立即淘汰
                            this.trimData();
                        }
                    }
                    
                    // 继续下一帧
                    this._autoScrollRAF = requestAnimationFrame(step);
                };
                
                this._autoScrollRAF = requestAnimationFrame(step);
            }

            // 停止自动滚动
            stopAutoScroll() {
                if (!this.isAutoScrolling) return;
                
                this.isAutoScrolling = false;
                this.startScrollBtn.disabled = false;
                this.stopScrollBtn.disabled = true;
                
                if (this._autoScrollRAF) {
                    cancelAnimationFrame(this._autoScrollRAF);
                    this._autoScrollRAF = null;
                }
                
                // 滚动停止后，执行一次数据淘汰检查
                this.trimData();
            }

            // 执行更新
            updateData() {
                try {
                    // 如果是自动滚动状态或不在加载中，生成要更新的数据
                    if (this.isAutoScrolling || !this.isLoading) {
                        // 根据数据量动态调整更新数量
                        const baseUpdateCount = Math.min(Math.max(20, this.batchSize / 10), 100); // 减少更新数量，提高性能
                        const updateCount = Math.min(baseUpdateCount, this.data.length);
                        
                        this.pendingUpdates = [];
                        
                        // 优先更新当前可见区域和缓冲区的数据
                        const visibleRange = {
                            start: Math.max(0, this.scrollIndex - this.bufferSize),
                            end: Math.min(this.data.length - 1, this.scrollIndex + this.maxCount + this.bufferSize)
                        };
                        
                        // 可见区域大小
                        const rangeSize = visibleRange.end - visibleRange.start + 1;
                        
                        // 如果可见区域有数据，优先更新可见区域
                        if (rangeSize > 0) {
                            // 从可见区域选择数据进行更新，确保均匀分布
                            const step = Math.max(1, Math.floor(rangeSize / updateCount));
                            for (let i = 0; i < updateCount; i++) {
                                const actualIndex = Math.min(visibleRange.start + (i * step), visibleRange.end);
                                if (actualIndex < this.data.length) {
                                    const id = this.data[actualIndex].id;
                                    this.pendingUpdates.push(generateDataItem(id));
                                }
                            }
                        } else if (this.data.length > 0) {
                            // 如果没有可见区域（可能滚动到底部），随机更新一些数据
                            for (let i = 0; i < updateCount && i < this.data.length; i++) {
                                const randomIndex = Math.floor(Math.random() * this.data.length);
                                const id = this.data[randomIndex].id;
                                this.pendingUpdates.push(generateDataItem(id));
                            }
                        }
                        
                        // 确保pendingUpdates中的数据按ID排序
                        this.pendingUpdates.sort((a, b) => a.id - b.id);
                    }
                    
                    // 更新滚动索引
                    this._updateScrollIndex();
                    
                    // 处理数据更新任务
                    this.processTaskQueue();
                    
                    // 仅当有可见行变化时更新视图
                    if (this.pendingUpdates.length > 0) {
                        this.updateVisibleRows();
                    }
                    
                    // 检查是否需要数据淘汰
                    if (this.data.length > this.maxDataLength * this.trimThreshold) {
                        this.trimData();
                    }
                } catch (error) {
                    this.errorHandlers.dataUpdate(error);
                }
            }

            // 处理更新任务队列
            processTaskQueue() {
                try {
                    while (this.taskQueue.length > 0) {
                        const task = this.taskQueue.shift();
                        try {
                            task();
                        } catch (taskError) {
                            console.error('任务执行失败:', taskError);
                            // 继续执行其他任务
                        }
                    }
                } catch (error) {
                    console.error('处理任务队列失败:', error);
                }
            }

            // 刷新数据
            refreshData() {
                try {
                    this.stopAutoScroll();
                    this.loadInitialData();
                } catch (error) {
                    console.error('刷新数据失败:', error);
                }
            }

            // 启动数据更新定时器
            startDataUpdateTimer() {
                this.stopDataUpdateTimer(); // 先停止旧的定时器
                
                // 使用更智能的定时更新策略：根据数据量和可见区域动态调整更新频率
                const getDynamicInterval = () => {
                    const dataAmountFactor = Math.min(this.data.length / 1000, 2); // 数据量越大，间隔越短
                    const baseInterval = this.dataUpdateInterval;
                    return Math.max(baseInterval / dataAmountFactor, 500); // 最小间隔500ms
                };
                
                this._updateTimer = setInterval(() => {
                    // 如果在自动滚动，增加更新频率
                    const intervalFactor = this.isAutoScrolling ? 0.5 : 1;
                    const shouldUpdate = Math.random() < (1 / intervalFactor);
                    
                    if (shouldUpdate) {
                        this.updateData();
                    }
                }, getDynamicInterval());
            }

            // 停止数据更新定时器
            stopDataUpdateTimer() {
                if (this._updateTimer) {
                    clearInterval(this._updateTimer);
                    this._updateTimer = null;
                }
            }

            // 更新配置
            updateOptions(options) {
                try {
                    this.scrollSpeed = options.scrollSpeed || this.scrollSpeed;
                    this.dataUpdateInterval = options.updateInterval || this.dataUpdateInterval;
                    this.batchSize = options.batchSize || this.batchSize;
                    this.maxDataLength = options.maxDataLength || this.maxDataLength;
                    this.trimThreshold = options.trimThreshold || this.trimThreshold;
                    this.trimInterval = options.trimInterval || this.trimInterval;
                    
                    // 如果提供了自定义行渲染器
                    if (options.rowRenderer) {
                        this.rowRenderer = options.rowRenderer;
                    }
                    
                    // 如果新的maxDataLength小于当前数据长度，立即执行数据淘汰
                    if (this.maxDataLength < this.data.length) {
                        this.trimData();
                    }
                    
                    // 重启定时器
                    this.startDataUpdateTimer();
                    this.startTrimTimer();
                    
                    // 重新渲染以应用新配置
                    this.updateVisibleRows();
                    
                    return true;
                } catch (error) {
                    console.error('更新配置失败:', error);
                    return false;
                }
            }

            // 获取当前状态信息（用于调试和监控）
            getStatus() {
                return {
                    totalDataCount: this.totalDataCount,
                    visibleDataCount: this.data.length,
                    currentScrollIndex: this.scrollIndex,
                    isAutoScrolling: this.isAutoScrolling,
                    isLoading: this.isLoading,
                    memoryUsageEstimate: `${Math.round(this.data.length * 1.5)}KB` // 估算内存使用
                };
            }

            // 清理资源
            cleanup() {
                try {
                    this.stopAutoScroll();
                    this.stopDataUpdateTimer();
                    this.stopTrimTimer();
                    
                    if (this._scrollRAF) {
                        cancelAnimationFrame(this._scrollRAF);
                        this._scrollRAF = null;
                    }
                    
                    // 清空数据和事件监听
                    this.data = [];
                    this.pendingUpdates = [];
                    this.rowHeights = [];
                    
                    // 移除事件监听器（避免内存泄漏）
                    this.container.removeEventListener('scroll', this._onScroll.bind(this));
                    this.startScrollBtn.removeEventListener('click', this.startAutoScroll.bind(this));
                    this.stopScrollBtn.removeEventListener('click', this.stopAutoScroll.bind(this));
                    this.refreshDataBtn.removeEventListener('click', this.refreshData.bind(this));
                    this.updateDataBtn.removeEventListener('click', this.updateData.bind(this));
                } catch (error) {
                    console.error('清理资源失败:', error);
                }
            }
        }

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', () => {
            // 获取配置
            const getConfig = () => ({
                scrollSpeed: parseInt(document.getElementById('scrollSpeed').value) || 3,
                updateInterval: parseInt(document.getElementById('updateInterval').value) || 3000,
                batchSize: parseInt(document.getElementById('batchSize').value) || 200,
                maxDataLength: 20000,
                trimThreshold: 0.7,
                trimInterval: 5000
            });

            // 初始化表格
            let virtualTable = new VirtualScrollTable(getConfig());

            // 应用配置按钮事件
            document.getElementById('applyConfig').addEventListener('click', () => {
                try {
                    const config = getConfig();
                    const success = virtualTable.updateOptions(config);
                    
                    if (success) {
                        // 显示更友好的成功提示
                        const statusInfo = virtualTable.getStatus();
                        const statusText = `\n\n当前状态:\n- 总数据量: ${statusInfo.totalDataCount}\n- 缓存数据量: ${statusInfo.visibleDataCount}\n- 内存估算: ${statusInfo.memoryUsageEstimate}`;
                        alert('配置已成功更新！' + statusText);
                    } else {
                        alert('配置更新失败，请检查输入值！');
                    }
                } catch (error) {
                    alert('应用配置时出错: ' + error.message);
                }
            });

            // 添加性能监控（可选）
            const monitorPerformance = () => {
                if (typeof performance !== 'undefined' && performance.now) {
                    const startTime = performance.now();
                    // 定期输出性能数据
                    setInterval(() => {
                        const elapsed = performance.now() - startTime;
                        if (elapsed > 60000) { // 每分钟重置一次
                            console.log('性能监控重置');
                            monitorPerformance();
                            return;
                        }
                        
                        const status = virtualTable.getStatus();
                        console.log(`表格性能监控: 数据量=${status.visibleDataCount}, 滚动位置=${status.currentScrollIndex}`);
                    }, 30000); // 每30秒输出一次
                }
            };
            
            // 仅在开发环境启用性能监控
            if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
                monitorPerformance();
            }

            // 页面卸载时清理
            window.addEventListener('beforeunload', () => {
                virtualTable.cleanup();
            });
        });
    </script>
</body>
</html>